package raft

import (
	"fmt"
	"math/rand"
	"sync"
)

type Store struct {
	timer int
	box   map[int]string
}

type Client struct {
	server *Leader
}

type Server struct {
	id string
}

type Cluster struct {
	node []*Server
}

type Leader struct {
	locker *sync.RWMutex // todo offset lock
	own    Server
	flows  []Server
}

var store Store

func init() {
	store = Store{timer: 0, box: make(map[int]string)}
}

func (s *Store) put(content string) (code int) {
	next := store.timer + 1
	store.timer = next
	s.box[store.timer] = content
	return 1 //覆盖写
}

func (s *Store) get(id int) string {
	return s.box[id]
}

func (c *Client) read(offset int) string {
	c.server.locker.RLocker()
	defer c.server.locker.RLock()
	return store.box[offset]
}

func (c *Client) write(content string) (offset, code int) {
	code = c.server.save(content)
	if code == 1 {
		return store.timer, 1
	}
	return -1, 0
}

// todo raft
func (s *Server) elect(cluster Cluster) *Server {
	return nil
}

func (s *Server) save(content string) (code int) {
	code = rand.Intn(2)
	if code == 1 {
		fmt.Printf("%s save log: %s\r\n", s.id, content)
	}
	return code
}

func (cluster *Cluster) electLeader() Leader {
	//nodes := cluster.node
	//storeCache := make(map[Server]int)
	//for _, node := range nodes {
	//	preLeader := node.elect(*cluster)
	//}

	// 成为候选人 todo

	// 成为领导

	return Leader{locker: new(sync.RWMutex), own: Server{"s1"},
		flows: []Server{{"s2"}, {"s3"}},
	}
}

func (l *Leader) save(log string) (code int) {
	l.locker.Lock()
	defer l.locker.Unlock()
	codeSum := 0
	codeSum += l.own.save(log)
	for _, f := range l.flows {
		codeSum += f.save(log)
	}

	//size := int(math.Ceil(3/2))
	size := 2
	if codeSum < size {
		return 0
	}

	return store.put(log)
}
